From: Sergej Proskurin Date: Wed, 16 Aug 2017 13:17:44 +0000 (+0200) Subject: arm/mem_access: Walk the guest's pt in software X-Git-Tag: archive/raspbian/4.11.1-1+rpi1~1^2~66^2~1641 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=bf3872d566972c9f8c7cd2b0e805d2d81da34dd3;p=xen.git arm/mem_access: Walk the guest's pt in software In this commit, we make use of the gpt walk functionality introduced in the previous commits. If mem_access is active, hardware-based gva to ipa translation might fail, as gva_to_ipa uses the guest's translation tables, access to which might be restricted by the active VTTBR. To side-step potential translation errors in the function p2m_mem_access_check_and_get_page due to restricted memory (e.g. to the guest's page tables themselves), we walk the guest's page tables in software. Signed-off-by: Sergej Proskurin Acked-by: Tamas K Lengyel Signed-off-by: Stefano Stabellini --- diff --git a/xen/arch/arm/mem_access.c b/xen/arch/arm/mem_access.c index e0888bbad2..3e2bb4088a 100644 --- a/xen/arch/arm/mem_access.c +++ b/xen/arch/arm/mem_access.c @@ -22,6 +22,7 @@ #include #include #include +#include static int __p2m_get_mem_access(struct domain *d, gfn_t gfn, xenmem_access_t *access) @@ -101,6 +102,7 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag, const struct vcpu *v) { long rc; + unsigned int perms; paddr_t ipa; gfn_t gfn; mfn_t mfn; @@ -110,8 +112,35 @@ p2m_mem_access_check_and_get_page(vaddr_t gva, unsigned long flag, struct p2m_domain *p2m = p2m_get_hostp2m(v->domain); rc = gva_to_ipa(gva, &ipa, flag); + + /* + * In case mem_access is active, hardware-based gva_to_ipa translation + * might fail. Since gva_to_ipa uses the guest's translation tables, access + * to which might be restricted by the active VTTBR, we perform a gva to + * ipa translation in software. + */ if ( rc < 0 ) - goto err; + { + /* + * The software gva to ipa translation can still fail, e.g., if the gva + * is not mapped. + */ + if ( guest_walk_tables(v, gva, &ipa, &perms) < 0 ) + goto err; + + /* + * Check permissions that are assumed by the caller. For instance in + * case of guestcopy, the caller assumes that the translated page can + * be accessed with requested permissions. If this is not the case, we + * should fail. + * + * Please note that we do not check for the GV2M_EXEC permission. Yet, + * since the hardware-based translation through gva_to_ipa does not + * test for execute permissions this check can be left out. + */ + if ( (flag & GV2M_WRITE) && !(perms & GV2M_WRITE) ) + goto err; + } gfn = gaddr_to_gfn(ipa);